iT邦幫忙

2024 iThome 鐵人賽

DAY 18
0
Software Development

深入淺出Java 30天系列 第 18

Day 18: 最小化可變性(上)

  • 分享至 

  • xImage
  •  

所謂最小化可變性,就是把類別盡量設計成immutable,immutable類別是指,在類別實體化之後,類別裡面的資料不能再被更動修改,因此,相較於mutable類別狀態的不確定性,immutable類別不管在設計、實作和使用上,都是比較簡潔和安全的,而且如果系統是multi-thread的設計,immutable類別也可以確保thread-safe,避免同一個物件對每個thread的狀態都不一致。而要如何設計immutable類別,我們可以遵循下面的規則:

  1. 不要提供任何可以修改物件狀態的方法
  2. 確保類別不能被繼承:避免繼承後的子類別改變父類別的行為,變成mutable的類別,最好把類別設為final防止被繼承。
  3. 把所有欄位設為final:這樣就可以避免其他使用者去更動欄位的值,當然,也可以確保thread之間的物件狀態不會被更動,造成資訊不一致的狀況。
  4. 把所有欄位設為private:如前面的曾經提過,雖然類別把欄位加了final屬性,但如果該欄位的值是reference而且是mutable,還是可以修改該欄位的狀態,為了避免這種情況,應該把欄位設為private
  5. 類別如果有包含mutable的物件,應避免其他類別以任何形式存取:如果有欄位是指向mutable物件的reference,應避免被其它使用者透過方法取得reference,當該欄位需要被存取時,可以使用defensive copy的方式回傳值給使用者。

而如果物件的狀態需要改變,可以回傳一個新的物件,既可避免原本的物件狀態被改變,又可以滿足新需求,下面的範例示範了,如何在狀態需要改變的時候,產生一個新的物件。

public final class Point {
    private final int x;
    private final int y;

    // Constructor
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // Getter methods
    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    // Method to move the point
    public Point move(int deltaX, int deltaY) {
        return new Point(this.x + deltaX, this.y + deltaY);
    }

    @Override
    public String toString() {
        return "Point{" + "x=" + x + ", y=" + y + '}';
    }

    public static void main(String[] args) {
        // Create a new Point
        Point p1 = new Point(0, 0);
        System.out.println("Original Point: " + p1);

        // Move the Point to a new location
        Point p2 = p1.move(5, 10);
        System.out.println("Moved Point: " + p2);

        // Verify that the original Point remains unchanged
        System.out.println("Original Point after move: " + p1);
    }
}

這樣可以確保物件是immutable,而且是thread-safe,不需要額外做同步。當然,除了這個方式之外,明天再介紹更多的方式讓物件保持immutable,也說說immutable物件的缺點,以及有什麼解法。


上一篇
Day 17: 最小化類別、方法和欄位的存取權限
下一篇
Day 19: 最小化可變性(下)
系列文
深入淺出Java 30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言